#include <bits/stdc++.h>
#define int long long
using namespace std;

const int maxn = 1e5+5;
int a[maxn];
int f[maxn][40];


int query(int l, int r){
	// 因为预处理使用了 倍增
	// 所以, 知道的一个区间中的最大/小值 有一个局限, 就是这个区间长度一定是 2的次幂
	// 所以想要知道任意一个区间中的最大/小值的话, 需要根据已有的区间来得出
	
	int k = (int)(log((r-l+1)*1.0)/log(2.0));
//	 其实就是区间长度为 r-l+1
//	 那么想要使用两个区间拼出来这个区间
//	 就是让 左部分的区间起始位置为 l
//	 右部分的区间的结束位置为 r
//	 并且需要确保这两个区间能交叉
//	 那么根据 f[i][j] 的含义, 直接让这两个区间的长度为 2^log(r-l+1)
//	 为什么是 2^log(r-l+1)
//	 因为我们已知的区间的最大/小值的长度全是 2 的次幂的
//	 第二 2^log(r-l+1) 是 <= r-l+1 的最大的长度(小于是因为 log(r-l+1)向下取整了)
//	 确保了两个区间是交叉的
	return min(f[l][k], f[r-(1<<k)+1][k]); // 得出的区间一定包含 [l, r]
}


void solve(){
	int n;
	cin >> n;
	// 2^0 长度的区间的最大/小值都是自身
	for (int i=1;i<=n;i++) {
		cin >> a[i];
		f[i][0] = a[i];
	}
	// 进行预处理
	// 状态转移
	for (int j=1;j<=(int)(log(n*1.0)/log(2.0));j++) {
		for (int i=1;(i+(1<<j)-1)<=n;i++) { // i 的范围是要使得右端不越界
			f[i][j] = min(f[i][j-1], f[i+(1<<(j-1))][j-1]); // 转移方程
		}
	}
	int q;
	cin >> 	q;
	while (q--) {
		int l, r;
		cin >> l >> r;
		int ans = query(l, r);
		cout << ans << '\n';
	}
}

signed main(){
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int t;
	t =1;
	cin >> t;
	while(t--){
		//TODO
		solve();
	}
	return 0;
}
